﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization;
using System.Xml.Serialization;

namespace Wumpus
{
    [DataContract]
    public class Position
    {
        public Position(List<Planet> Planets, List<List<int>> connections) : this(Planets, connections, 0) {}
        public Position(List<Planet> Planets, List<List<int>> connections, int Player)
        {
            this.Planets = Planets; this.Player = Player;

            for (int i = 0; i < Planets.Count; i++)
                Planets[i] = new Planet(Planets[i], connections[i], i);
        }

        [DataMember]
        public readonly List<Planet> Planets;
        [DataMember]
        public int Player { get; set; }

        public T GetNearest<T>(int StartPos) where T : Hazard
        {
            //TODO: Design Algorithm
            return (T)Activator.CreateInstance(typeof(T));
        }

        public void MoveHazard(Hazard hazard, int NewIndex)
        {
            int CurrentIndex = hazard.CurrentPlanet.Index;

            if (hazard.CurrentPlanet.IsConnectedTo(NewIndex) && Planets[NewIndex].IsVacant())
            {
                Planets[NewIndex].Hazard = hazard;
                Planets[CurrentIndex].Hazard = null;
            }

            else throw new Exception("Room not connected");
        }

    }

    [DataContract]
    public class Planet
    {
        public Planet(): this(new Inventory(), null) { }
        public Planet(Inventory inventory): this(inventory, null) { }
        public Planet(Inventory inventory, Hazard hazard)
        {
            if (hazard != null) this.Hazard = hazard; this.Inventory = inventory;
        }
        public Planet(Planet planet, List<int> connections, int index)
            : this(planet.Inventory, planet.Hazard)
        {
            this.Index = index; this.Connections = connections; //only for use by Position class
        }

        [DataMember]
        public Inventory Inventory;
        [IgnoreDataMember]
        internal readonly int Index;               //only for use by Position class
        [IgnoreDataMember]
        internal readonly List<int> Connections;   //only for use by Position class
        private Hazard pHazard;

        [DataMember]
        public Hazard Hazard
        {
            get { return pHazard; }
            set { if (value != null) value.CurrentPlanet = this; this.pHazard = value; }
        }

        //[System.Xml.Serialization.XmlIgnore] //determines if serialization appropriate
        //public bool HazardSpecified { get { return this.Hazard != null; } } //property must be named this

        public T GetHazard<T>() where T : Hazard // only if you're sure of the type
        {
            if (this.Hazard is T) return (T)(object)this.Hazard;
            else throw new Exception("Wrong hazard type!");
        }

        public bool IsConnectedTo(int index)
        {
            for (int i = 0; i < Connections.Count; i++)
                if (Index == Connections[i]) return true;

            return false;
        }

        public bool IsVacant()
        {
            if (this.Hazard == null) return true;
            else return false;
        }
    }

}